﻿using System;
using GeoAPI.Geometries;

namespace NetTopologySuite.Precision
{
	public class CommonBitsOp
	{
		public CommonBitsOp() : this(true)
		{
		}

		public CommonBitsOp(bool returnToOriginalPrecision)
		{
			this._returnToOriginalPrecision = returnToOriginalPrecision;
		}

		public IGeometry Intersection(IGeometry geom0, IGeometry geom1)
		{
			IGeometry[] array = this.RemoveCommonBits(geom0, geom1);
			return this.ComputeResultPrecision(array[0].Intersection(array[1]));
		}

		public IGeometry Union(IGeometry geom0, IGeometry geom1)
		{
			IGeometry[] array = this.RemoveCommonBits(geom0, geom1);
			return this.ComputeResultPrecision(array[0].Union(array[1]));
		}

		public IGeometry Difference(IGeometry geom0, IGeometry geom1)
		{
			IGeometry[] array = this.RemoveCommonBits(geom0, geom1);
			return this.ComputeResultPrecision(array[0].Difference(array[1]));
		}

		public IGeometry SymDifference(IGeometry geom0, IGeometry geom1)
		{
			IGeometry[] array = this.RemoveCommonBits(geom0, geom1);
			return this.ComputeResultPrecision(array[0].SymmetricDifference(array[1]));
		}

		public IGeometry Buffer(IGeometry geom0, double distance)
		{
			IGeometry geometry = this.RemoveCommonBits(geom0);
			return this.ComputeResultPrecision(geometry.Buffer(distance));
		}

		private IGeometry ComputeResultPrecision(IGeometry result)
		{
			if (this._returnToOriginalPrecision)
			{
				this._cbr.AddCommonBits(result);
			}
			return result;
		}

		private IGeometry RemoveCommonBits(IGeometry geom0)
		{
			this._cbr = new CommonBitsRemover();
			this._cbr.Add(geom0);
			return this._cbr.RemoveCommonBits((IGeometry)geom0.Clone());
		}

		private IGeometry[] RemoveCommonBits(IGeometry geom0, IGeometry geom1)
		{
			this._cbr = new CommonBitsRemover();
			this._cbr.Add(geom0);
			this._cbr.Add(geom1);
			return new IGeometry[]
			{
				this._cbr.RemoveCommonBits((IGeometry)geom0.Clone()),
				this._cbr.RemoveCommonBits((IGeometry)geom1.Clone())
			};
		}

		private readonly bool _returnToOriginalPrecision = true;

		private CommonBitsRemover _cbr;
	}
}
